package com.itheima.aspects;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.itheima.enums.ClassDescEnum;
import com.itheima.pojo.LogEntity;
import com.itheima.service.LogService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 拦截有的contorller,记录所有的增删改查操作
 */
@Aspect
@Component
public class UserOperatorLogAspect {
//    ThreadLocal threadLocal = new ThreadLocal();

    @Reference
    private LogService logService;

    /**
     * 这里解的我们使用注形式
     * 当然，我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method
     * 切点表达式:   execution(...)
     */
    @Pointcut("execution(* com.itheima.controller..*.*(..))")
    public void logPointCut() {
    }

    /**
     * 环绕通知 @Around  ， 当然也可以使用 @Before (前置通知)  @After (后置通知)
     *
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        Object[] args = point.getArgs();
//        for (Object arg : args) {
//            threadLocal.set(args);
//        }
        Object result = point.proceed();
        try {
            saveLog(point,result);
        } catch (Exception e) {
        }
        return result;
    }

    /**
     * 保存日志
     *
     * @param joinPoint
     */
    private void saveLog(ProceedingJoinPoint joinPoint,Object result) {
        String className = joinPoint.getTarget().getClass().getName();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String name = signature.getName();
        if (name.contains("add") || name.contains("del") || name.contains("edit")) {
            String header = ClassDescEnum.getClassMsg(className);
            try {
                LogEntity logEntity = new LogEntity();
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                String currentUserName = authentication.getName();
                logEntity.setOperator(currentUserName);
                if (name.contains("add")) {
                    logEntity.setMsg(stringBuilder("添加",header));
                }
                if (name.contains("del")) {
                    logEntity.setMsg(stringBuilder("删除",header));
                }
                if (name.contains("edit")) {
                    logEntity.setMsg(stringBuilder("修改",header));
                }
                logEntity.setType(name);
                logEntity.setIn_time(new Date());
                logEntity.setMod_time(new Date());
                logEntity.setStatus(checkStatus(result));
//                logEntity.setStatus(new Short("1"));
                logService.saveLog(logEntity);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 验证返回结果是否正确
     * @param result
     * @return short 1 失败,  2 成功
     */
    private Short checkStatus(Object result) {
        if(null==result){
            return new Short("1");
        }
        System.out.println(JSON.toJSONString(result));
        JSONObject parse1 = (JSONObject) JSONObject.parse(JSON.toJSONString(result));
        Object flag = parse1.get("flag");
        if(null!=flag){
            if(String.valueOf(flag).equals("true")){
                return new Short("2");
            }else if(String.valueOf(flag).equals("false")){
                return new Short("1");
            }else {
                return new Short("3");//未知
            }
        }
        return new Short("3");
    }

    /**
     * 字符串拼接
     * @param header
     * @param msg
     * @return
     */
    private String stringBuilder(String msg,String header){
        if(!StringUtils.isEmpty(header)){
            return msg+header;
        }
        return msg;
    }

}
